#include "drpc.h"
#include "drpc_netproto_def.h"
#include "netproto_cli.h"
#include <stdio.h>
#include <string.h>

#include <sys/time.h>
#include <pthread.h>
#include <assert.h>

int Drpc_NetProtoAdd(int a, int b, int* rerr)
{
  int err = DRPC_NP_ERR_SUCCESS;
  int c;
  int handle = drpc_call_core_input_param_cli PARM2(0, DRPC_NP_CMD_BUILTINTYPE, a, b);
  if (handle < 0) {
    err = DRPC_NP_ERR_INPUT;
    goto finish;
  }
  else {
    int ret = drpc_call_core_output_param_cli PARM1(handle, DRPC_NP_CMD_BUILTINTYPE, c);
    drpc_call_core_end_cli(handle);
    if (ret < 0) {
      printf("Drpc_NetProtoAdd drpc_call_core_output_param_cli=%d\r\n", ret);
      err = DRPC_NP_ERR_OUTPUT;
      goto finish;
    }
  }

finish:
  if (rerr) *rerr = err;
  if (err != DRPC_NP_ERR_SUCCESS) {
    return -1;
  }
  return c;
}

void Drpc_NetProtoGetStu(MyStu_t* t, int* rerr)
{
  int err = DRPC_NP_ERR_SUCCESS;

  int handle = drpc_call_core_input_param_cli PARM1(0, DRPC_NP_CMD_PASSSTRUCT, *t);
  if (handle < 0) {
    err = DRPC_NP_ERR_INPUT;
    goto finish;
  } else {
    int ret = drpc_call_core_output_param_cli PARM1(handle, DRPC_NP_CMD_PASSSTRUCT, *t);
    drpc_call_core_end_cli(handle);
    if (ret < 0) {
      err = DRPC_NP_ERR_OUTPUT;
      goto finish;
    }
  }

finish:
  if (rerr) *rerr = err;
}

void Drpc_NetProtoGetStr(char* s, int* rerr)
{
  int err = DRPC_NP_ERR_SUCCESS;
  int len = strlen(s);
  if (len >= sizeof(MyStr_t)) return;
  MyStr_t str_t = {0};
  strncpy(str_t.szStr, s, sizeof(str_t.szStr)-1);

  int handle = drpc_call_core_input_param_cli PARM1(0, DRPC_NP_CMD_PASSSTRING, str_t);
  if (handle < 0) {
    err = DRPC_NP_ERR_INPUT;
    goto finish;
  }
  else {
    int ret = drpc_call_core_output_param_cli PARM1(handle, DRPC_NP_CMD_PASSSTRING, str_t);
    drpc_call_core_end_cli(handle);
    if (ret < 0) {
      err = DRPC_NP_ERR_OUTPUT;
      goto finish;
    } else {
        strncpy(s, str_t.szStr, 31);
    }
  }

finish:
  if (rerr) *rerr = err;
}



void* sub_routine(void* args)
{
  // benchmark test
  int count = 50000;
  struct timeval tv_s, tv_e;
  gettimeofday(&tv_s, NULL);
  while (count--) {
    /******** 1 ********/
    int a = 2;
    int b = 8;
    int c = 0;
    int err;
    c = Drpc_NetProtoAdd(a, b, &err);
    assert(c == a+b);
    //if (err == DRPC_NP_ERR_SUCCESS) {
    //  //printf("%d+%d=%d\r\n", a, b,c);
    //} else {
    //  printf("call failed\r\n");
    //}

    /******** 2 ********/
    MyStu_t t = {"Alice", 20};
    Drpc_NetProtoGetStu(&t, &err);
    //if (err  == DRPC_NP_ERR_SUCCESS) {
    //  printf("Name:%s,Age:%d\r\n", t.szName, t.nAge);
    //} else {
    //  printf("call failed\r\n");
    //}

    /******** 3 ********/
    char s[32] = "str from client";
    Drpc_NetProtoGetStr(s, &err);
    //if (err == DRPC_NP_ERR_SUCCESS) {
    //  printf("Str:%s\r\n", s);
    //} else {
    //  printf("call failed\r\n");
    //}
  }
  gettimeofday(&tv_e, NULL);
  printf("elapsed: %lu ms\r\n", (tv_e.tv_sec*1000+tv_e.tv_usec/1000)-(tv_s.tv_sec*1000+tv_s.tv_usec/1000));

  return 0;
}

int main()
{
    pthread_t tids[5];
    for (int i = 0; i < 5; i++) {
        pthread_create(&tids[i], NULL, sub_routine, NULL);
    }
    for (int i = 0; i < 5; i++) {
        pthread_join(tids[i], NULL);
    }
    return 0;
}
